package controller

import (
	"fmt"

	"github.com/gin-gonic/gin"
	"github.com/itstonight/ziyue/controller/rsp"
	"github.com/itstonight/ziyue/db"
	"github.com/itstonight/ziyue/models"
	"github.com/itstonight/ziyue/pkg/strings"
	"golang.org/x/crypto/bcrypt"
)

type LoginReq struct {
	Phone    string `json:"phone" binding:"required"`
	Password string `json:"password" binding:"required"`
}

type RegisterReq struct {
	Phone    string `json:"phone" binding:"required"`
	Name     string `json:"name" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func Login(ctx *gin.Context) {
	var req LoginReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		rsp.Fail(ctx, err)
		return
	}

	var user models.User
	result := db.Client.WithContext(ctx).Where("phone = ?", req.Phone).First(&user)
	if result.Error != nil {
		// 使用统一错误消息避免泄露用户存在信息
		rsp.FailWithMsg(ctx, "账号或者密码错误")
		return
	}

	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
		rsp.FailWithMsg(ctx, "账号或者密码错误")
		return
	}

	// 先删除该用户的旧token
	db.Client.WithContext(ctx).Where("user_id = ?", user.ID).Delete(&models.Token{})

	tokenModel := models.Token{
		UserID: user.ID,
		Token:  strings.RandomString(32),
	}

	if err := db.Client.WithContext(ctx).Create(&tokenModel).Error; err != nil {
		rsp.Fail(ctx, fmt.Errorf("创建token失败: %w", err))
		return
	}

	tokenModel.User = &user

	rsp.LoginResponse(ctx, &tokenModel)
}

func Register(ctx *gin.Context) {
	var req RegisterReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		rsp.Fail(ctx, err)
		return
	}

	// 检查手机号是否已经注册
	var user models.User
	if err := db.Client.WithContext(ctx).Where("phone = ?", req.Phone).First(&user).Error; err == nil {
		rsp.FailWithMsg(ctx, "该手机号已经注册")
		return
	}

	password, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		rsp.Fail(ctx, err)
		return
	}

	user = models.User{
		Phone:    req.Phone,
		Username: req.Name,
		Password: string(password),
		Role:     1,
	}

	if err := db.Client.WithContext(ctx).Create(&user).Error; err != nil {
		rsp.Fail(ctx, fmt.Errorf("注册失败: %w", err))
		return
	}

	tokenModel := models.Token{
		UserID: user.ID,
		Token:  strings.RandomString(32),
	}

	if err := db.Client.WithContext(ctx).Create(&tokenModel).Error; err != nil {
		rsp.Fail(ctx, fmt.Errorf("创建token失败: %w", err))
		return
	}

	tokenModel.User = &user
	rsp.LoginResponse(ctx, &tokenModel)
}

func CurrentUser(ctx *gin.Context) {
	u, _ := ctx.Get("user")
	rsp.Success(ctx, u)
}
